Implement Debug helpers via Cell#159302
Conversation
|
|
|
Details; ModuleID = 'repro.95a4099cea1845-cgu.0'
source_filename = "repro.95a4099cea1845-cgu.0"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "arm64-apple-macosx11.0.0"
@alloc_fe2ddbdc622a788f5416063d1e8d8ad4 = private unnamed_addr constant [3 x i8] c" { ", align 1
@alloc_94b00be069aafad82a2c6df764237b82 = private unnamed_addr constant [2 x i8] c", ", align 1
@alloc_556e4180596b5b612bb6ed6c0cbb55e1 = private unnamed_addr constant [2 x i8] c": ", align 1
@alloc_3690db001d3db01550bdb6f3f450de28 = private unnamed_addr constant [3 x i8] c" {\0A", align 1
@alloc_f7ac0c356c6ac6fcd03badb685e09ca2 = private unnamed_addr constant [2 x i8] c",\0A", align 1
@alloc_bf0ef947d182249ea2203578272460c5 = private unnamed_addr constant [5 x i8] c"Point", align 1
@alloc_37f62a15fae368a2423b3a16c75adcc9 = private unnamed_addr constant [1 x i8] c"x", align 1
@alloc_cd51bc84b49b21a3fdb2800731f25c21 = private unnamed_addr constant [1 x i8] c"y", align 1
; <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#0}>
; Function Attrs: uwtable
define align 8 ptr @_RINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1f_5PointNtB8_5Debug3fmt0EB1f_(ptr align 8 %self, ptr %name.0, i64 %name.1, ptr align 4 %value_fmt) unnamed_addr #0 {
start:
%_8 = alloca [32 x i8], align 8
%op = alloca [32 x i8], align 8
%_4 = alloca [1 x i8], align 1
%0 = getelementptr inbounds i8, ptr %self, i64 8
%1 = load i8, ptr %0, align 8
%self1 = trunc nuw i8 %1 to i1
store ptr %self, ptr %op, align 8
%2 = getelementptr inbounds i8, ptr %op, i64 8
store ptr %name.0, ptr %2, align 8
%3 = getelementptr inbounds i8, ptr %2, i64 8
store i64 %name.1, ptr %3, align 8
%4 = getelementptr inbounds i8, ptr %op, i64 24
store ptr %value_fmt, ptr %4, align 8
%_7 = zext i1 %self1 to i64
%5 = trunc nuw i64 %_7 to i1
br i1 %5, label %bb3, label %bb4
bb3: ; preds = %start
store i8 1, ptr %_4, align 1
br label %bb1
bb4: ; preds = %start
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %_8, ptr align 8 %op, i64 32, i1 false)
; call <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#0}>::{closure#0}
%6 = call zeroext i1 @_RNCINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB8_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1h_5PointNtBa_5Debug3fmt0E0B1h_(ptr align 8 %_8) #4
%7 = zext i1 %6 to i8
store i8 %7, ptr %_4, align 1
br label %bb1
bb1: ; preds = %bb3, %bb4
%8 = getelementptr inbounds i8, ptr %self, i64 8
%9 = load i8, ptr %_4, align 1
%10 = trunc nuw i8 %9 to i1
%11 = zext i1 %10 to i8
store i8 %11, ptr %8, align 8
%12 = getelementptr inbounds i8, ptr %self, i64 9
store i8 1, ptr %12, align 1
ret ptr %self
bb2: ; No predecessors!
unreachable
}
; <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#1}>
; Function Attrs: uwtable
define align 8 ptr @_RINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1f_5PointNtB8_5Debug3fmts_0EB1f_(ptr align 8 %self, ptr %name.0, i64 %name.1, ptr align 4 %value_fmt) unnamed_addr #0 {
start:
%_8 = alloca [32 x i8], align 8
%op = alloca [32 x i8], align 8
%_4 = alloca [1 x i8], align 1
%0 = getelementptr inbounds i8, ptr %self, i64 8
%1 = load i8, ptr %0, align 8
%self1 = trunc nuw i8 %1 to i1
store ptr %self, ptr %op, align 8
%2 = getelementptr inbounds i8, ptr %op, i64 8
store ptr %name.0, ptr %2, align 8
%3 = getelementptr inbounds i8, ptr %2, i64 8
store i64 %name.1, ptr %3, align 8
%4 = getelementptr inbounds i8, ptr %op, i64 24
store ptr %value_fmt, ptr %4, align 8
%_7 = zext i1 %self1 to i64
%5 = trunc nuw i64 %_7 to i1
br i1 %5, label %bb3, label %bb4
bb3: ; preds = %start
store i8 1, ptr %_4, align 1
br label %bb1
bb4: ; preds = %start
call void @llvm.memcpy.p0.p0.i64(ptr align 8 %_8, ptr align 8 %op, i64 32, i1 false)
; call <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#1}>::{closure#0}
%6 = call zeroext i1 @_RNCINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB8_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1h_5PointNtBa_5Debug3fmts_0E0B1h_(ptr align 8 %_8) #4
%7 = zext i1 %6 to i8
store i8 %7, ptr %_4, align 1
br label %bb1
bb1: ; preds = %bb3, %bb4
%8 = getelementptr inbounds i8, ptr %self, i64 8
%9 = load i8, ptr %_4, align 1
%10 = trunc nuw i8 %9 to i1
%11 = zext i1 %10 to i8
store i8 %11, ptr %8, align 8
%12 = getelementptr inbounds i8, ptr %self, i64 9
store i8 1, ptr %12, align 1
ret ptr %self
bb2: ; No predecessors!
unreachable
}
; <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#0}>::{closure#0}
; Function Attrs: inlinehint uwtable
define zeroext i1 @_RNCINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB8_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1h_5PointNtBa_5Debug3fmt0E0B1h_(ptr align 8 %_1) unnamed_addr #1 personality ptr @rust_eh_personality {
start:
%0 = alloca [16 x i8], align 8
%_50 = alloca [1 x i8], align 1
%prefix = alloca [16 x i8], align 8
%writer = alloca [24 x i8], align 8
%state = alloca [1 x i8], align 1
%slot = alloca [24 x i8], align 8
%_0 = alloca [1 x i8], align 1
store i8 1, ptr %_50, align 1
%self = load ptr, ptr %_1, align 8
%_51 = load ptr, ptr %self, align 8
%1 = getelementptr inbounds i8, ptr %_51, i64 16
%_53 = load i32, ptr %1, align 8
%_52 = and i32 %_53, 8388608
%2 = icmp eq i32 %_52, 0
br i1 %2, label %bb11, label %bb1
bb11: ; preds = %start
%_40 = load ptr, ptr %_1, align 8
%3 = getelementptr inbounds i8, ptr %_40, i64 9
%4 = load i8, ptr %3, align 1
%_24 = trunc nuw i8 %4 to i1
br i1 %_24, label %bb12, label %bb13
bb1: ; preds = %start
%_34 = load ptr, ptr %_1, align 8
%5 = getelementptr inbounds i8, ptr %_34, i64 9
%6 = load i8, ptr %5, align 1
%_3 = trunc nuw i8 %6 to i1
br i1 %_3, label %bb5, label %bb2
bb13: ; preds = %bb11
store ptr @alloc_fe2ddbdc622a788f5416063d1e8d8ad4, ptr %prefix, align 8, !captures !4
%7 = getelementptr inbounds i8, ptr %prefix, i64 8
store i64 3, ptr %7, align 8
br label %bb14
bb12: ; preds = %bb11
store ptr @alloc_94b00be069aafad82a2c6df764237b82, ptr %prefix, align 8, !captures !4
%8 = getelementptr inbounds i8, ptr %prefix, i64 8
store i64 2, ptr %8, align 8
br label %bb14
bb14: ; preds = %bb12, %bb13
%_41 = load ptr, ptr %_1, align 8
%_42 = load ptr, ptr %_41, align 8
%9 = load ptr, ptr %prefix, align 8
%10 = getelementptr inbounds i8, ptr %prefix, i64 8
%11 = load i64, ptr %10, align 8
; invoke <core::fmt::Formatter>::write_str
%self1 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_42, ptr %9, i64 %11)
to label %bb15 unwind label %cleanup
bb24: ; preds = %cleanup
%12 = load i8, ptr %_50, align 1
%13 = trunc nuw i8 %12 to i1
br i1 %13, label %bb23, label %bb22
cleanup: ; preds = %bb32, %bb30, %bb28, %bb6, %bb5, %bb2, %bb38, %bb36, %bb34, %bb14
%14 = landingpad { ptr, i32 }
cleanup
%15 = extractvalue { ptr, i32 } %14, 0
%16 = extractvalue { ptr, i32 } %14, 1
store ptr %15, ptr %0, align 8
%17 = getelementptr inbounds i8, ptr %0, i64 8
store i32 %16, ptr %17, align 8
br label %bb24
bb15: ; preds = %bb14
%_66 = zext i1 %self1 to i64
%18 = trunc nuw i64 %_66 to i1
br i1 %18, label %bb33, label %bb34
bb33: ; preds = %bb15
store i8 1, ptr %_0, align 1
br label %bb20
bb34: ; preds = %bb15
%_43 = load ptr, ptr %_1, align 8
%_44 = load ptr, ptr %_43, align 8
%19 = getelementptr inbounds i8, ptr %_1, i64 8
%_45.0 = load ptr, ptr %19, align 8
%20 = getelementptr inbounds i8, ptr %19, i64 8
%_45.1 = load i64, ptr %20, align 8
; invoke <core::fmt::Formatter>::write_str
%self2 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_44, ptr %_45.0, i64 %_45.1)
to label %bb16 unwind label %cleanup
bb16: ; preds = %bb34
%_69 = zext i1 %self2 to i64
%21 = trunc nuw i64 %_69 to i1
br i1 %21, label %bb35, label %bb36
bb35: ; preds = %bb16
store i8 1, ptr %_0, align 1
br label %bb20
bb36: ; preds = %bb16
%_46 = load ptr, ptr %_1, align 8
%_47 = load ptr, ptr %_46, align 8
; invoke <core::fmt::Formatter>::write_str
%self3 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_47, ptr @alloc_556e4180596b5b612bb6ed6c0cbb55e1, i64 2)
to label %bb17 unwind label %cleanup
bb17: ; preds = %bb36
%_72 = zext i1 %self3 to i64
%22 = trunc nuw i64 %_72 to i1
br i1 %22, label %bb37, label %bb38
bb37: ; preds = %bb17
store i8 1, ptr %_0, align 1
br label %bb20
bb38: ; preds = %bb17
store i8 0, ptr %_50, align 1
%23 = getelementptr inbounds i8, ptr %_1, i64 24
%_31 = load ptr, ptr %23, align 8
%_48 = load ptr, ptr %_1, align 8
%_49 = load ptr, ptr %_48, align 8
; invoke <repro::Point as core::fmt::Debug>::fmt::{closure#0}
%24 = invoke zeroext i1 @_RNCNvXCs36UsywoTqr_5reproNtB4_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmt0B4_(ptr align 4 %_31, ptr align 8 %_49)
to label %bb18 unwind label %cleanup
bb18: ; preds = %bb38
%25 = zext i1 %24 to i8
store i8 %25, ptr %_0, align 1
br label %bb19
bb19: ; preds = %bb10, %bb18
br label %bb21
bb20: ; preds = %bb33, %bb35, %bb37
br label %bb40
bb40: ; preds = %bb39, %bb25, %bb20
br label %bb21
bb2: ; preds = %bb1
%_35 = load ptr, ptr %_1, align 8
%_36 = load ptr, ptr %_35, align 8
; invoke <core::fmt::Formatter>::write_str
%self4 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_36, ptr @alloc_3690db001d3db01550bdb6f3f450de28, i64 3)
to label %bb3 unwind label %cleanup
bb5: ; preds = %bb26, %bb1
store ptr null, ptr %slot, align 8
store i8 1, ptr %state, align 1
%_37 = load ptr, ptr %_1, align 8
%_38 = load ptr, ptr %_37, align 8
; invoke <core::fmt::builders::PadAdapter>::wrap
invoke void @_RNvMs_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB4_10PadAdapter4wrap(ptr sret([24 x i8]) align 8 %writer, ptr align 8 %_38, ptr align 8 %slot, ptr %state)
to label %bb6 unwind label %cleanup
bb3: ; preds = %bb2
%_54 = zext i1 %self4 to i64
%26 = trunc nuw i64 %_54 to i1
br i1 %26, label %bb25, label %bb26
bb25: ; preds = %bb3
store i8 1, ptr %_0, align 1
br label %bb40
bb26: ; preds = %bb3
br label %bb5
bb6: ; preds = %bb5
%27 = getelementptr inbounds i8, ptr %_1, i64 8
%_39.0 = load ptr, ptr %27, align 8
%28 = getelementptr inbounds i8, ptr %27, i64 8
%_39.1 = load i64, ptr %28, align 8
; invoke <core::fmt::Formatter>::write_str
%self5 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %writer, ptr %_39.0, i64 %_39.1)
to label %bb7 unwind label %cleanup
bb7: ; preds = %bb6
%_57 = zext i1 %self5 to i64
%29 = trunc nuw i64 %_57 to i1
br i1 %29, label %bb27, label %bb28
bb27: ; preds = %bb7
store i8 1, ptr %_0, align 1
br label %bb39
bb28: ; preds = %bb7
; invoke <core::fmt::Formatter>::write_str
%self6 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %writer, ptr @alloc_556e4180596b5b612bb6ed6c0cbb55e1, i64 2)
to label %bb8 unwind label %cleanup
bb8: ; preds = %bb28
%_60 = zext i1 %self6 to i64
%30 = trunc nuw i64 %_60 to i1
br i1 %30, label %bb29, label %bb30
bb29: ; preds = %bb8
store i8 1, ptr %_0, align 1
br label %bb39
bb30: ; preds = %bb8
store i8 0, ptr %_50, align 1
%31 = getelementptr inbounds i8, ptr %_1, i64 24
%_18 = load ptr, ptr %31, align 8
; invoke <repro::Point as core::fmt::Debug>::fmt::{closure#0}
%self7 = invoke zeroext i1 @_RNCNvXCs36UsywoTqr_5reproNtB4_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmt0B4_(ptr align 4 %_18, ptr align 8 %writer)
to label %bb9 unwind label %cleanup
bb9: ; preds = %bb30
%_63 = zext i1 %self7 to i64
%32 = trunc nuw i64 %_63 to i1
br i1 %32, label %bb31, label %bb32
bb31: ; preds = %bb9
store i8 1, ptr %_0, align 1
br label %bb21
bb32: ; preds = %bb9
; invoke <core::fmt::Formatter>::write_str
%33 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %writer, ptr @alloc_f7ac0c356c6ac6fcd03badb685e09ca2, i64 2)
to label %bb10 unwind label %cleanup
bb10: ; preds = %bb32
%34 = zext i1 %33 to i8
store i8 %34, ptr %_0, align 1
br label %bb19
bb21: ; preds = %bb40, %bb31, %bb19
%35 = load i8, ptr %_0, align 1
%36 = trunc nuw i8 %35 to i1
ret i1 %36
bb39: ; preds = %bb27, %bb29
br label %bb40
bb4: ; No predecessors!
unreachable
bb22: ; preds = %bb23, %bb24
%37 = load ptr, ptr %0, align 8
%38 = getelementptr inbounds i8, ptr %0, i64 8
%39 = load i32, ptr %38, align 8
%40 = insertvalue { ptr, i32 } poison, ptr %37, 0
%41 = insertvalue { ptr, i32 } %40, i32 %39, 1
resume { ptr, i32 } %41
bb23: ; preds = %bb24
br label %bb22
}
; <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#1}>::{closure#0}
; Function Attrs: inlinehint uwtable
define zeroext i1 @_RNCINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB8_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1h_5PointNtBa_5Debug3fmts_0E0B1h_(ptr align 8 %_1) unnamed_addr #1 personality ptr @rust_eh_personality {
start:
%0 = alloca [16 x i8], align 8
%_50 = alloca [1 x i8], align 1
%prefix = alloca [16 x i8], align 8
%writer = alloca [24 x i8], align 8
%state = alloca [1 x i8], align 1
%slot = alloca [24 x i8], align 8
%_0 = alloca [1 x i8], align 1
store i8 1, ptr %_50, align 1
%self = load ptr, ptr %_1, align 8
%_51 = load ptr, ptr %self, align 8
%1 = getelementptr inbounds i8, ptr %_51, i64 16
%_53 = load i32, ptr %1, align 8
%_52 = and i32 %_53, 8388608
%2 = icmp eq i32 %_52, 0
br i1 %2, label %bb11, label %bb1
bb11: ; preds = %start
%_40 = load ptr, ptr %_1, align 8
%3 = getelementptr inbounds i8, ptr %_40, i64 9
%4 = load i8, ptr %3, align 1
%_24 = trunc nuw i8 %4 to i1
br i1 %_24, label %bb12, label %bb13
bb1: ; preds = %start
%_34 = load ptr, ptr %_1, align 8
%5 = getelementptr inbounds i8, ptr %_34, i64 9
%6 = load i8, ptr %5, align 1
%_3 = trunc nuw i8 %6 to i1
br i1 %_3, label %bb5, label %bb2
bb13: ; preds = %bb11
store ptr @alloc_fe2ddbdc622a788f5416063d1e8d8ad4, ptr %prefix, align 8, !captures !4
%7 = getelementptr inbounds i8, ptr %prefix, i64 8
store i64 3, ptr %7, align 8
br label %bb14
bb12: ; preds = %bb11
store ptr @alloc_94b00be069aafad82a2c6df764237b82, ptr %prefix, align 8, !captures !4
%8 = getelementptr inbounds i8, ptr %prefix, i64 8
store i64 2, ptr %8, align 8
br label %bb14
bb14: ; preds = %bb12, %bb13
%_41 = load ptr, ptr %_1, align 8
%_42 = load ptr, ptr %_41, align 8
%9 = load ptr, ptr %prefix, align 8
%10 = getelementptr inbounds i8, ptr %prefix, i64 8
%11 = load i64, ptr %10, align 8
; invoke <core::fmt::Formatter>::write_str
%self1 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_42, ptr %9, i64 %11)
to label %bb15 unwind label %cleanup
bb24: ; preds = %cleanup
%12 = load i8, ptr %_50, align 1
%13 = trunc nuw i8 %12 to i1
br i1 %13, label %bb23, label %bb22
cleanup: ; preds = %bb32, %bb30, %bb28, %bb6, %bb5, %bb2, %bb38, %bb36, %bb34, %bb14
%14 = landingpad { ptr, i32 }
cleanup
%15 = extractvalue { ptr, i32 } %14, 0
%16 = extractvalue { ptr, i32 } %14, 1
store ptr %15, ptr %0, align 8
%17 = getelementptr inbounds i8, ptr %0, i64 8
store i32 %16, ptr %17, align 8
br label %bb24
bb15: ; preds = %bb14
%_66 = zext i1 %self1 to i64
%18 = trunc nuw i64 %_66 to i1
br i1 %18, label %bb33, label %bb34
bb33: ; preds = %bb15
store i8 1, ptr %_0, align 1
br label %bb20
bb34: ; preds = %bb15
%_43 = load ptr, ptr %_1, align 8
%_44 = load ptr, ptr %_43, align 8
%19 = getelementptr inbounds i8, ptr %_1, i64 8
%_45.0 = load ptr, ptr %19, align 8
%20 = getelementptr inbounds i8, ptr %19, i64 8
%_45.1 = load i64, ptr %20, align 8
; invoke <core::fmt::Formatter>::write_str
%self2 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_44, ptr %_45.0, i64 %_45.1)
to label %bb16 unwind label %cleanup
bb16: ; preds = %bb34
%_69 = zext i1 %self2 to i64
%21 = trunc nuw i64 %_69 to i1
br i1 %21, label %bb35, label %bb36
bb35: ; preds = %bb16
store i8 1, ptr %_0, align 1
br label %bb20
bb36: ; preds = %bb16
%_46 = load ptr, ptr %_1, align 8
%_47 = load ptr, ptr %_46, align 8
; invoke <core::fmt::Formatter>::write_str
%self3 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_47, ptr @alloc_556e4180596b5b612bb6ed6c0cbb55e1, i64 2)
to label %bb17 unwind label %cleanup
bb17: ; preds = %bb36
%_72 = zext i1 %self3 to i64
%22 = trunc nuw i64 %_72 to i1
br i1 %22, label %bb37, label %bb38
bb37: ; preds = %bb17
store i8 1, ptr %_0, align 1
br label %bb20
bb38: ; preds = %bb17
store i8 0, ptr %_50, align 1
%23 = getelementptr inbounds i8, ptr %_1, i64 24
%_31 = load ptr, ptr %23, align 8
%_48 = load ptr, ptr %_1, align 8
%_49 = load ptr, ptr %_48, align 8
; invoke <repro::Point as core::fmt::Debug>::fmt::{closure#1}
%24 = invoke zeroext i1 @_RNCNvXCs36UsywoTqr_5reproNtB4_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmts_0B4_(ptr align 4 %_31, ptr align 8 %_49)
to label %bb18 unwind label %cleanup
bb18: ; preds = %bb38
%25 = zext i1 %24 to i8
store i8 %25, ptr %_0, align 1
br label %bb19
bb19: ; preds = %bb10, %bb18
br label %bb21
bb20: ; preds = %bb33, %bb35, %bb37
br label %bb40
bb40: ; preds = %bb39, %bb25, %bb20
br label %bb21
bb2: ; preds = %bb1
%_35 = load ptr, ptr %_1, align 8
%_36 = load ptr, ptr %_35, align 8
; invoke <core::fmt::Formatter>::write_str
%self4 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %_36, ptr @alloc_3690db001d3db01550bdb6f3f450de28, i64 3)
to label %bb3 unwind label %cleanup
bb5: ; preds = %bb26, %bb1
store ptr null, ptr %slot, align 8
store i8 1, ptr %state, align 1
%_37 = load ptr, ptr %_1, align 8
%_38 = load ptr, ptr %_37, align 8
; invoke <core::fmt::builders::PadAdapter>::wrap
invoke void @_RNvMs_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB4_10PadAdapter4wrap(ptr sret([24 x i8]) align 8 %writer, ptr align 8 %_38, ptr align 8 %slot, ptr %state)
to label %bb6 unwind label %cleanup
bb3: ; preds = %bb2
%_54 = zext i1 %self4 to i64
%26 = trunc nuw i64 %_54 to i1
br i1 %26, label %bb25, label %bb26
bb25: ; preds = %bb3
store i8 1, ptr %_0, align 1
br label %bb40
bb26: ; preds = %bb3
br label %bb5
bb6: ; preds = %bb5
%27 = getelementptr inbounds i8, ptr %_1, i64 8
%_39.0 = load ptr, ptr %27, align 8
%28 = getelementptr inbounds i8, ptr %27, i64 8
%_39.1 = load i64, ptr %28, align 8
; invoke <core::fmt::Formatter>::write_str
%self5 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %writer, ptr %_39.0, i64 %_39.1)
to label %bb7 unwind label %cleanup
bb7: ; preds = %bb6
%_57 = zext i1 %self5 to i64
%29 = trunc nuw i64 %_57 to i1
br i1 %29, label %bb27, label %bb28
bb27: ; preds = %bb7
store i8 1, ptr %_0, align 1
br label %bb39
bb28: ; preds = %bb7
; invoke <core::fmt::Formatter>::write_str
%self6 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %writer, ptr @alloc_556e4180596b5b612bb6ed6c0cbb55e1, i64 2)
to label %bb8 unwind label %cleanup
bb8: ; preds = %bb28
%_60 = zext i1 %self6 to i64
%30 = trunc nuw i64 %_60 to i1
br i1 %30, label %bb29, label %bb30
bb29: ; preds = %bb8
store i8 1, ptr %_0, align 1
br label %bb39
bb30: ; preds = %bb8
store i8 0, ptr %_50, align 1
%31 = getelementptr inbounds i8, ptr %_1, i64 24
%_18 = load ptr, ptr %31, align 8
; invoke <repro::Point as core::fmt::Debug>::fmt::{closure#1}
%self7 = invoke zeroext i1 @_RNCNvXCs36UsywoTqr_5reproNtB4_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmts_0B4_(ptr align 4 %_18, ptr align 8 %writer)
to label %bb9 unwind label %cleanup
bb9: ; preds = %bb30
%_63 = zext i1 %self7 to i64
%32 = trunc nuw i64 %_63 to i1
br i1 %32, label %bb31, label %bb32
bb31: ; preds = %bb9
store i8 1, ptr %_0, align 1
br label %bb21
bb32: ; preds = %bb9
; invoke <core::fmt::Formatter>::write_str
%33 = invoke zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8 %writer, ptr @alloc_f7ac0c356c6ac6fcd03badb685e09ca2, i64 2)
to label %bb10 unwind label %cleanup
bb10: ; preds = %bb32
%34 = zext i1 %33 to i8
store i8 %34, ptr %_0, align 1
br label %bb19
bb21: ; preds = %bb40, %bb31, %bb19
%35 = load i8, ptr %_0, align 1
%36 = trunc nuw i8 %35 to i1
ret i1 %36
bb39: ; preds = %bb27, %bb29
br label %bb40
bb4: ; No predecessors!
unreachable
bb22: ; preds = %bb23, %bb24
%37 = load ptr, ptr %0, align 8
%38 = getelementptr inbounds i8, ptr %0, i64 8
%39 = load i32, ptr %38, align 8
%40 = insertvalue { ptr, i32 } poison, ptr %37, 0
%41 = insertvalue { ptr, i32 } %40, i32 %39, 1
resume { ptr, i32 } %41
bb23: ; preds = %bb24
br label %bb22
}
; <repro::Point as core::fmt::Debug>::fmt::{closure#0}
; Function Attrs: inlinehint uwtable
define internal zeroext i1 @_RNCNvXCs36UsywoTqr_5reproNtB4_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmt0B4_(ptr align 4 %_1, ptr align 8 %f) unnamed_addr #1 {
start:
; call <u32 as core::fmt::Debug>::fmt
%_0 = call zeroext i1 @_RNvXsW_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_5Debug3fmtCs36UsywoTqr_5repro(ptr align 4 %_1, ptr align 8 %f) #4
ret i1 %_0
}
; <repro::Point as core::fmt::Debug>::fmt::{closure#1}
; Function Attrs: inlinehint uwtable
define internal zeroext i1 @_RNCNvXCs36UsywoTqr_5reproNtB4_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmts_0B4_(ptr align 4 %_1, ptr align 8 %f) unnamed_addr #1 {
start:
%_3 = getelementptr inbounds i8, ptr %_1, i64 4
; call <u32 as core::fmt::Debug>::fmt
%_0 = call zeroext i1 @_RNvXsW_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_5Debug3fmtCs36UsywoTqr_5repro(ptr align 4 %_3, ptr align 8 %f) #4
ret i1 %_0
}
; <repro::Point as core::fmt::Debug>::fmt
; Function Attrs: uwtable
define zeroext i1 @_RNvXCs36UsywoTqr_5reproNtB2_5PointNtNtCs2xrpM2fV95l_4core3fmt5Debug3fmt(ptr align 4 %self, ptr align 8 %f) unnamed_addr #0 {
start:
%_6 = alloca [16 x i8], align 8
; call <core::fmt::Formatter>::debug_struct
call void @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter12debug_struct(ptr sret([16 x i8]) align 8 %_6, ptr align 8 %f, ptr @alloc_bf0ef947d182249ea2203578272460c5, i64 5)
; call <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#0}>
%_4 = call align 8 ptr @_RINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1f_5PointNtB8_5Debug3fmt0EB1f_(ptr align 8 %_6, ptr @alloc_37f62a15fae368a2423b3a16c75adcc9, i64 1, ptr align 4 %self)
; call <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#1}>
%_3 = call align 8 ptr @_RINvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCs36UsywoTqr_5reproNtB1f_5PointNtB8_5Debug3fmts_0EB1f_(ptr align 8 %_4, ptr @alloc_cd51bc84b49b21a3fdb2800731f25c21, i64 1, ptr align 4 %self)
; call <core::fmt::builders::DebugStruct>::finish
%_0 = call zeroext i1 @_RNvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB5_11DebugStruct6finish(ptr align 8 %_3)
ret i1 %_0
}
; <u32 as core::fmt::Debug>::fmt
; Function Attrs: inlinehint uwtable
define internal zeroext i1 @_RNvXsW_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_5Debug3fmtCs36UsywoTqr_5repro(ptr align 4 %self, ptr align 8 %f) unnamed_addr #1 {
start:
%_0 = alloca [1 x i8], align 1
%0 = getelementptr inbounds i8, ptr %f, i64 16
%_4 = load i32, ptr %0, align 8
%_3 = and i32 %_4, 33554432
%1 = icmp eq i32 %_3, 0
br i1 %1, label %bb2, label %bb1
bb2: ; preds = %start
%2 = getelementptr inbounds i8, ptr %f, i64 16
%_6 = load i32, ptr %2, align 8
%_5 = and i32 %_6, 67108864
%3 = icmp eq i32 %_5, 0
br i1 %3, label %bb4, label %bb3
bb1: ; preds = %start
; call <u32 as core::fmt::LowerHex>::fmt
%4 = call zeroext i1 @_RNvXsu_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_8LowerHex3fmt(ptr align 4 %self, ptr align 8 %f)
%5 = zext i1 %4 to i8
store i8 %5, ptr %_0, align 1
br label %bb6
bb4: ; preds = %bb2
; call <u32 as core::fmt::Display>::fmt
%6 = call zeroext i1 @_RNvXs8_NtNtNtCs2xrpM2fV95l_4core3fmt3num3impmNtB9_7Display3fmt(ptr align 4 %self, ptr align 8 %f)
%7 = zext i1 %6 to i8
store i8 %7, ptr %_0, align 1
br label %bb5
bb3: ; preds = %bb2
; call <u32 as core::fmt::UpperHex>::fmt
%8 = call zeroext i1 @_RNvXsw_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_8UpperHex3fmt(ptr align 4 %self, ptr align 8 %f)
%9 = zext i1 %8 to i8
store i8 %9, ptr %_0, align 1
br label %bb5
bb5: ; preds = %bb3, %bb4
br label %bb6
bb6: ; preds = %bb1, %bb5
%10 = load i8, ptr %_0, align 1
%11 = trunc nuw i8 %10 to i1
ret i1 %11
}
; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #2
; Function Attrs: nounwind uwtable
declare i32 @rust_eh_personality(i32, i32, i64, ptr, ptr) unnamed_addr #3
; <core::fmt::Formatter>::write_str
; Function Attrs: uwtable
declare zeroext i1 @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter9write_str(ptr align 8, ptr, i64) unnamed_addr #0
; <core::fmt::builders::PadAdapter>::wrap
; Function Attrs: uwtable
declare void @_RNvMs_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB4_10PadAdapter4wrap(ptr sret([24 x i8]) align 8, ptr align 8, ptr align 8, ptr) unnamed_addr #0
; <core::fmt::Formatter>::debug_struct
; Function Attrs: uwtable
declare void @_RNvMsa_NtCs2xrpM2fV95l_4core3fmtNtB5_9Formatter12debug_struct(ptr sret([16 x i8]) align 8, ptr align 8, ptr, i64) unnamed_addr #0
; <core::fmt::builders::DebugStruct>::finish
; Function Attrs: uwtable
declare zeroext i1 @_RNvMs1_NtNtCs2xrpM2fV95l_4core3fmt8buildersNtB5_11DebugStruct6finish(ptr align 8) unnamed_addr #0
; <u32 as core::fmt::Display>::fmt
; Function Attrs: uwtable
declare zeroext i1 @_RNvXs8_NtNtNtCs2xrpM2fV95l_4core3fmt3num3impmNtB9_7Display3fmt(ptr align 4, ptr align 8) unnamed_addr #0
; <u32 as core::fmt::UpperHex>::fmt
; Function Attrs: uwtable
declare zeroext i1 @_RNvXsw_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_8UpperHex3fmt(ptr align 4, ptr align 8) unnamed_addr #0
; <u32 as core::fmt::LowerHex>::fmt
; Function Attrs: uwtable
declare zeroext i1 @_RNvXsu_NtNtCs2xrpM2fV95l_4core3fmt3nummNtB7_8LowerHex3fmt(ptr align 4, ptr align 8) unnamed_addr #0
attributes #0 = { uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #1 = { inlinehint uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #2 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
attributes #3 = { nounwind uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #4 = { inlinehint }
!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}
!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 7, !"uwtable", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 1}
!3 = !{!"rustc version 1.99.0-nightly (77cf889bc 2026-07-12)"}
!4 = !{!"address", !"read_provenance"}
Details; ModuleID = 'repro.ada4be50ab0d3186-cgu.0'
source_filename = "repro.ada4be50ab0d3186-cgu.0"
target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-n32:64-S128-Fn32"
target triple = "arm64-apple-macosx11.0.0"
@vtable.0 = private unnamed_addr constant <{ [24 x i8], ptr }> <{ [24 x i8] c"\00\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00", ptr @_RNvXs1_NtNtCs1Jl4pBjAano_4core3fmt8buildersINtB5_9DebugOnceNCNvXCseUiCQVDuJCY_5reproNtB10_5PointNtB7_5Debug3fmt0EB1w_3fmtB10_ }>, align 8
@vtable.1 = private unnamed_addr constant <{ [24 x i8], ptr }> <{ [24 x i8] c"\00\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00\08\00\00\00\00\00\00\00", ptr @_RNvXs1_NtNtCs1Jl4pBjAano_4core3fmt8buildersINtB5_9DebugOnceNCNvXCseUiCQVDuJCY_5reproNtB10_5PointNtB7_5Debug3fmts_0EB1w_3fmtB10_ }>, align 8
@alloc_bf0ef947d182249ea2203578272460c5 = private unnamed_addr constant [5 x i8] c"Point", align 1
@alloc_37f62a15fae368a2423b3a16c75adcc9 = private unnamed_addr constant [1 x i8] c"x", align 1
@alloc_cd51bc84b49b21a3fdb2800731f25c21 = private unnamed_addr constant [1 x i8] c"y", align 1
@alloc_67658ef8123446d70a96e7dbc7651d58 = private unnamed_addr constant [40 x i8] c"formatting closure called more than once", align 1
@alloc_703b1d677d4c28a67f1910a45c16864b = private unnamed_addr constant [33 x i8] c"library/core/src/fmt/builders.rs\00", align 1
@alloc_7fd203ad775cd664e43a5c0ae4634671 = private unnamed_addr constant <{ ptr, [16 x i8] }> <{ ptr @alloc_703b1d677d4c28a67f1910a45c16864b, [16 x i8] c" \00\00\00\00\00\00\00H\00\00\00\15\00\00\00" }>, align 8
; <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#0}>
; Function Attrs: uwtable
define align 8 ptr @_RINvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCseUiCQVDuJCY_5reproNtB1f_5PointNtB8_5Debug3fmt0EB1f_(ptr align 8 %self, ptr %name.0, i64 %name.1, ptr align 4 %value_fmt) unnamed_addr #0 personality ptr @rust_eh_personality {
start:
%0 = alloca [16 x i8], align 8
%_6 = alloca [8 x i8], align 8
store ptr %value_fmt, ptr %_6, align 8
; invoke <core::fmt::builders::DebugStruct>::field
%_0 = invoke align 8 ptr @_RNvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB5_11DebugStruct5field(ptr align 8 %self, ptr %name.0, i64 %name.1, ptr %_6, ptr align 8 @vtable.0)
to label %bb1 unwind label %cleanup
bb3: ; preds = %cleanup
%1 = load ptr, ptr %0, align 8
%2 = getelementptr inbounds i8, ptr %0, i64 8
%3 = load i32, ptr %2, align 8
%4 = insertvalue { ptr, i32 } poison, ptr %1, 0
%5 = insertvalue { ptr, i32 } %4, i32 %3, 1
resume { ptr, i32 } %5
cleanup: ; preds = %start
%6 = landingpad { ptr, i32 }
cleanup
%7 = extractvalue { ptr, i32 } %6, 0
%8 = extractvalue { ptr, i32 } %6, 1
store ptr %7, ptr %0, align 8
%9 = getelementptr inbounds i8, ptr %0, i64 8
store i32 %8, ptr %9, align 8
br label %bb3
bb1: ; preds = %start
ret ptr %_0
}
; <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#1}>
; Function Attrs: uwtable
define align 8 ptr @_RINvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCseUiCQVDuJCY_5reproNtB1f_5PointNtB8_5Debug3fmts_0EB1f_(ptr align 8 %self, ptr %name.0, i64 %name.1, ptr align 4 %value_fmt) unnamed_addr #0 personality ptr @rust_eh_personality {
start:
%0 = alloca [16 x i8], align 8
%_6 = alloca [8 x i8], align 8
store ptr %value_fmt, ptr %_6, align 8
; invoke <core::fmt::builders::DebugStruct>::field
%_0 = invoke align 8 ptr @_RNvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB5_11DebugStruct5field(ptr align 8 %self, ptr %name.0, i64 %name.1, ptr %_6, ptr align 8 @vtable.1)
to label %bb1 unwind label %cleanup
bb3: ; preds = %cleanup
%1 = load ptr, ptr %0, align 8
%2 = getelementptr inbounds i8, ptr %0, i64 8
%3 = load i32, ptr %2, align 8
%4 = insertvalue { ptr, i32 } poison, ptr %1, 0
%5 = insertvalue { ptr, i32 } %4, i32 %3, 1
resume { ptr, i32 } %5
cleanup: ; preds = %start
%6 = landingpad { ptr, i32 }
cleanup
%7 = extractvalue { ptr, i32 } %6, 0
%8 = extractvalue { ptr, i32 } %6, 1
store ptr %7, ptr %0, align 8
%9 = getelementptr inbounds i8, ptr %0, i64 8
store i32 %8, ptr %9, align 8
br label %bb3
bb1: ; preds = %start
ret ptr %_0
}
; <repro::Point as core::fmt::Debug>::fmt::{closure#0}
; Function Attrs: inlinehint uwtable
define internal zeroext i1 @_RNCNvXCseUiCQVDuJCY_5reproNtB4_5PointNtNtCs1Jl4pBjAano_4core3fmt5Debug3fmt0B4_(ptr align 4 %_1, ptr align 8 %f) unnamed_addr #1 {
start:
; call <u32 as core::fmt::Debug>::fmt
%_0 = call zeroext i1 @_RNvXsW_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_5Debug3fmtCseUiCQVDuJCY_5repro(ptr align 4 %_1, ptr align 8 %f) #4
ret i1 %_0
}
; <repro::Point as core::fmt::Debug>::fmt::{closure#1}
; Function Attrs: inlinehint uwtable
define internal zeroext i1 @_RNCNvXCseUiCQVDuJCY_5reproNtB4_5PointNtNtCs1Jl4pBjAano_4core3fmt5Debug3fmts_0B4_(ptr align 4 %_1, ptr align 8 %f) unnamed_addr #1 {
start:
%_3 = getelementptr inbounds i8, ptr %_1, i64 4
; call <u32 as core::fmt::Debug>::fmt
%_0 = call zeroext i1 @_RNvXsW_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_5Debug3fmtCseUiCQVDuJCY_5repro(ptr align 4 %_3, ptr align 8 %f) #4
ret i1 %_0
}
; <repro::Point as core::fmt::Debug>::fmt
; Function Attrs: uwtable
define zeroext i1 @_RNvXCseUiCQVDuJCY_5reproNtB2_5PointNtNtCs1Jl4pBjAano_4core3fmt5Debug3fmt(ptr align 4 %self, ptr align 8 %f) unnamed_addr #0 {
start:
%_6 = alloca [16 x i8], align 8
; call <core::fmt::Formatter>::debug_struct
call void @_RNvMsa_NtCs1Jl4pBjAano_4core3fmtNtB5_9Formatter12debug_struct(ptr sret([16 x i8]) align 8 %_6, ptr align 8 %f, ptr @alloc_bf0ef947d182249ea2203578272460c5, i64 5)
; call <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#0}>
%_4 = call align 8 ptr @_RINvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCseUiCQVDuJCY_5reproNtB1f_5PointNtB8_5Debug3fmt0EB1f_(ptr align 8 %_6, ptr @alloc_37f62a15fae368a2423b3a16c75adcc9, i64 1, ptr align 4 %self)
; call <core::fmt::builders::DebugStruct>::field_with::<<repro::Point as core::fmt::Debug>::fmt::{closure#1}>
%_3 = call align 8 ptr @_RINvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB6_11DebugStruct10field_withNCNvXCseUiCQVDuJCY_5reproNtB1f_5PointNtB8_5Debug3fmts_0EB1f_(ptr align 8 %_4, ptr @alloc_cd51bc84b49b21a3fdb2800731f25c21, i64 1, ptr align 4 %self)
; call <core::fmt::builders::DebugStruct>::finish
%_0 = call zeroext i1 @_RNvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB5_11DebugStruct6finish(ptr align 8 %_3)
ret i1 %_0
}
; <core::fmt::builders::DebugOnce<<repro::Point as core::fmt::Debug>::fmt::{closure#0}> as core::fmt::Debug>::fmt
; Function Attrs: uwtable
define zeroext i1 @_RNvXs1_NtNtCs1Jl4pBjAano_4core3fmt8buildersINtB5_9DebugOnceNCNvXCseUiCQVDuJCY_5reproNtB10_5PointNtB7_5Debug3fmt0EB1w_3fmtB10_(ptr align 8 %self, ptr align 8 %f) unnamed_addr #0 {
start:
%_3 = alloca [8 x i8], align 8
%0 = load ptr, ptr %self, align 8
store ptr %0, ptr %_3, align 8
store ptr null, ptr %self, align 8
%1 = load ptr, ptr %_3, align 8
%2 = ptrtoint ptr %1 to i64
%3 = icmp eq i64 %2, 0
%_5 = select i1 %3, i64 0, i64 1
%4 = trunc nuw i64 %_5 to i1
br i1 %4, label %bb3, label %bb2
bb3: ; preds = %start
%value_fmt = load ptr, ptr %_3, align 8
; call <repro::Point as core::fmt::Debug>::fmt::{closure#0}
%_0 = call zeroext i1 @_RNCNvXCseUiCQVDuJCY_5reproNtB4_5PointNtNtCs1Jl4pBjAano_4core3fmt5Debug3fmt0B4_(ptr align 4 %value_fmt, ptr align 8 %f) #4
ret i1 %_0
bb2: ; preds = %start
; call core::panicking::panic_fmt
call void @_RNvNtCs1Jl4pBjAano_4core9panicking9panic_fmt(ptr @alloc_67658ef8123446d70a96e7dbc7651d58, ptr inttoptr (i64 81 to ptr), ptr align 8 @alloc_7fd203ad775cd664e43a5c0ae4634671) #5
unreachable
bb1: ; No predecessors!
unreachable
}
; <core::fmt::builders::DebugOnce<<repro::Point as core::fmt::Debug>::fmt::{closure#1}> as core::fmt::Debug>::fmt
; Function Attrs: uwtable
define zeroext i1 @_RNvXs1_NtNtCs1Jl4pBjAano_4core3fmt8buildersINtB5_9DebugOnceNCNvXCseUiCQVDuJCY_5reproNtB10_5PointNtB7_5Debug3fmts_0EB1w_3fmtB10_(ptr align 8 %self, ptr align 8 %f) unnamed_addr #0 {
start:
%_3 = alloca [8 x i8], align 8
%0 = load ptr, ptr %self, align 8
store ptr %0, ptr %_3, align 8
store ptr null, ptr %self, align 8
%1 = load ptr, ptr %_3, align 8
%2 = ptrtoint ptr %1 to i64
%3 = icmp eq i64 %2, 0
%_5 = select i1 %3, i64 0, i64 1
%4 = trunc nuw i64 %_5 to i1
br i1 %4, label %bb3, label %bb2
bb3: ; preds = %start
%value_fmt = load ptr, ptr %_3, align 8
; call <repro::Point as core::fmt::Debug>::fmt::{closure#1}
%_0 = call zeroext i1 @_RNCNvXCseUiCQVDuJCY_5reproNtB4_5PointNtNtCs1Jl4pBjAano_4core3fmt5Debug3fmts_0B4_(ptr align 4 %value_fmt, ptr align 8 %f) #4
ret i1 %_0
bb2: ; preds = %start
; call core::panicking::panic_fmt
call void @_RNvNtCs1Jl4pBjAano_4core9panicking9panic_fmt(ptr @alloc_67658ef8123446d70a96e7dbc7651d58, ptr inttoptr (i64 81 to ptr), ptr align 8 @alloc_7fd203ad775cd664e43a5c0ae4634671) #5
unreachable
bb1: ; No predecessors!
unreachable
}
; <u32 as core::fmt::Debug>::fmt
; Function Attrs: inlinehint uwtable
define internal zeroext i1 @_RNvXsW_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_5Debug3fmtCseUiCQVDuJCY_5repro(ptr align 4 %self, ptr align 8 %f) unnamed_addr #1 {
start:
%_0 = alloca [1 x i8], align 1
%0 = getelementptr inbounds i8, ptr %f, i64 16
%_4 = load i32, ptr %0, align 8
%_3 = and i32 %_4, 33554432
%1 = icmp eq i32 %_3, 0
br i1 %1, label %bb2, label %bb1
bb2: ; preds = %start
%2 = getelementptr inbounds i8, ptr %f, i64 16
%_6 = load i32, ptr %2, align 8
%_5 = and i32 %_6, 67108864
%3 = icmp eq i32 %_5, 0
br i1 %3, label %bb4, label %bb3
bb1: ; preds = %start
; call <u32 as core::fmt::LowerHex>::fmt
%4 = call zeroext i1 @_RNvXsu_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_8LowerHex3fmt(ptr align 4 %self, ptr align 8 %f)
%5 = zext i1 %4 to i8
store i8 %5, ptr %_0, align 1
br label %bb6
bb4: ; preds = %bb2
; call <u32 as core::fmt::Display>::fmt
%6 = call zeroext i1 @_RNvXs8_NtNtNtCs1Jl4pBjAano_4core3fmt3num3impmNtB9_7Display3fmt(ptr align 4 %self, ptr align 8 %f)
%7 = zext i1 %6 to i8
store i8 %7, ptr %_0, align 1
br label %bb5
bb3: ; preds = %bb2
; call <u32 as core::fmt::UpperHex>::fmt
%8 = call zeroext i1 @_RNvXsw_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_8UpperHex3fmt(ptr align 4 %self, ptr align 8 %f)
%9 = zext i1 %8 to i8
store i8 %9, ptr %_0, align 1
br label %bb5
bb5: ; preds = %bb3, %bb4
br label %bb6
bb6: ; preds = %bb1, %bb5
%10 = load i8, ptr %_0, align 1
%11 = trunc nuw i8 %10 to i1
ret i1 %11
}
; Function Attrs: nounwind uwtable
declare i32 @rust_eh_personality(i32, i32, i64, ptr, ptr) unnamed_addr #2
; <core::fmt::builders::DebugStruct>::field
; Function Attrs: uwtable
declare align 8 ptr @_RNvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB5_11DebugStruct5field(ptr align 8, ptr, i64, ptr, ptr align 8) unnamed_addr #0
; <core::fmt::Formatter>::debug_struct
; Function Attrs: uwtable
declare void @_RNvMsa_NtCs1Jl4pBjAano_4core3fmtNtB5_9Formatter12debug_struct(ptr sret([16 x i8]) align 8, ptr align 8, ptr, i64) unnamed_addr #0
; <core::fmt::builders::DebugStruct>::finish
; Function Attrs: uwtable
declare zeroext i1 @_RNvMs2_NtNtCs1Jl4pBjAano_4core3fmt8buildersNtB5_11DebugStruct6finish(ptr align 8) unnamed_addr #0
; core::panicking::panic_fmt
; Function Attrs: cold noinline noreturn uwtable
declare void @_RNvNtCs1Jl4pBjAano_4core9panicking9panic_fmt(ptr, ptr, ptr align 8) unnamed_addr #3
; <u32 as core::fmt::Display>::fmt
; Function Attrs: uwtable
declare zeroext i1 @_RNvXs8_NtNtNtCs1Jl4pBjAano_4core3fmt3num3impmNtB9_7Display3fmt(ptr align 4, ptr align 8) unnamed_addr #0
; <u32 as core::fmt::UpperHex>::fmt
; Function Attrs: uwtable
declare zeroext i1 @_RNvXsw_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_8UpperHex3fmt(ptr align 4, ptr align 8) unnamed_addr #0
; <u32 as core::fmt::LowerHex>::fmt
; Function Attrs: uwtable
declare zeroext i1 @_RNvXsu_NtNtCs1Jl4pBjAano_4core3fmt3nummNtB7_8LowerHex3fmt(ptr align 4, ptr align 8) unnamed_addr #0
attributes #0 = { uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #1 = { inlinehint uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #2 = { nounwind uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #3 = { cold noinline noreturn uwtable "frame-pointer"="non-leaf" "probe-stack"="inline-asm" "target-cpu"="apple-m1" }
attributes #4 = { inlinehint }
attributes #5 = { noinline noreturn }
!llvm.module.flags = !{!0, !1, !2}
!llvm.ident = !{!3}
!0 = !{i32 8, !"PIC Level", i32 2}
!1 = !{i32 7, !"uwtable", i32 2}
!2 = !{i32 7, !"frame-pointer", i32 1}
!3 = !{!"rustc version 1.99.0-dev"} |
Debug helpers that take closures with &mut dyn FnMut
|
r? me (happy to hand this back to @tgross35 if that’s preferred) @bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Implement `Debug` helpers that take closures with `&mut dyn FnMut`
|
Oh thats fine @hanna-kruppe I just didn't know if you were in the rotation (I've only ever directly requested from 2 other people total in the past 🤣) |
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (d43d144): comparison URL. Overall result: ❌✅ regressions and improvements - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (secondary 3.0%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (secondary -2.7%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeResults (primary -0.2%, secondary 0.3%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Bootstrap: 491.202s -> 491.87s (0.14%) |
|
optional: As discussed in the other thread, since the pre-existing struct DebugOnce<F>(Cell<Option<F>>);
impl<F> fmt::Debug for DebugOnce<F>
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(x) = self.0.replace(None) {
return (x)(f);
}
Ok(())
}
}
// ...
pub fn field_with<F>(&mut self, name: &str, value_fmt: F) -> &mut Self
where
F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result,
{
self.field(name, &DebugOnce(Cell::new(Some(value_fmt))))
} |
No need, all yours :) |
|
@jmillikin could you help me understand why using this |
|
I wrote a bigger test program to compare the growth as number of
The "per field" column is just the extra lines of 6 vs 3 fields and 9 vs 6 fields divided by 3. Not sure why it's not an integer. Don't read too much into it. I also skimmed the LLVM IR generated for
I guess @jmillikin's approach side-steps the third problem by not involving closure trait objects. |
There was a problem hiding this comment.
By my measurements above, this PR does improve things significantly. But DebugStruct::field_with vs field still seems to be a ca 10x difference in LLVM IR per call site despite that improvement. I'd like to take the improvements anyway and try to squeeze out more gains in a follow up PR, but it looks like there's a runtime performance regression right now. So if you're up for it, I'd suggest trying the approach described by @jmillikin.
|
Reminder, once the PR becomes ready for a review, use |
Signed-off-by: Connor Tsui <connor.tsui20@gmail.com>
8dd6849 to
b727274
Compare
Debug helpers that take closures with &mut dyn FnMutDebug helpers via Cell
|
@rustbot ready |
|
@bors try @rust-timer queue |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
Implement `Debug` helpers via `Cell`
This comment has been minimized.
This comment has been minimized.
|
Finished benchmarking commit (fcf8e93): comparison URL. Overall result: ❌ regressions - no action neededBenchmarking means the PR may be perf-sensitive. Consider adding rollup=never if this change is not fit for rolling up. @rustbot label: -S-waiting-on-perf -perf-regression Instruction countOur most reliable metric. Used to determine the overall result above. However, even this metric can be noisy.
Max RSS (memory usage)Results (primary 1.0%, secondary 4.6%)A less reliable metric. May be of interest, but not used to determine the overall result above.
CyclesResults (primary 1.8%, secondary 0.1%)A less reliable metric. May be of interest, but not used to determine the overall result above.
Binary sizeThis perf run didn't have relevant results for this metric. Bootstrap: 487.651s -> 489.459s (0.37%) |
There was a problem hiding this comment.
Is there any way we could reasonably cover this in a codegen test?
There was a problem hiding this comment.
I've asked myself that on other changes to reduce monomorphization, and I never came up with a satisfying answer. Matching against the structure of calling some shared monomorphic function is the closest thing, but that's not really reasonable because it's either way too unspecific or way too sensitive to details like function names.
There was a problem hiding this comment.
It would probably be a good idea to add a benchmark using these functions to https://github.com/rust-lang/rustc-perf/tree/2e1f10b49224c069b9fdca7fe8d1e78790e8c62b/collector, assuming the differences here make it to optimized binary size.
There was a problem hiding this comment.
I don’t think this is worth it in the grand scheme of things. We shouldn’t have an API that’s an unavoidable code size footgun to use at all, but also, this one API isn’t likely to be a sufficiently interesting benchmark for the purpose of rustc-perf, compared to everything else we could be measuring with the limited benchmarking budget. If this API eventually makes its way into a popular application/library, we may measure it that way in a more realistic setting.
Also, yeah, it doesn’t necessarily show up in optimized binary size. The examples we’ve had so far get handled well by function merging so they act mostly like a single field_with call. It’s likely possible to write a microbenchmark that doesn’t have so much obviously identical code, but the real risk is death by a thousand cuts across a large code base, which is hard to model in an artificial benchmark.
|
I repeated the previous experiment with the
That's better but honestly still not great. Although a lot of the difference is due to debug info related overhead (the
And a lot of the remaining IR is the aforementioned (1) |
|
As another point of comparison, I extended my test with a variant that uses
|
| fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
| match self.0.take() { | ||
| Some(value_fmt) => value_fmt(f), | ||
| None => panic!("formatting closure called more than once"), |
There was a problem hiding this comment.
Are we sure that the panic is optimized out? If not, this should probably return Ok? Even if by some chance this branch were reached, probably better not to panic anyways.
|
On the one hand, this PR in its current state is a good contribution that I'd be happy to merge: it significantly reduces the cost of On the other hand, I don't feel this fully fixes #149745. So @connortsui20 I would propose merging this PR minus the "Fixes #149745" bit. And then someone will need to do further work in another PR to fully close that issue. If you're up for it, I can sketch the ideas I have and you try them out. If not, I might try my hand at that myself, after having thought a bunch about it, but I can't promise when I'll get around to it. Does that sound okay to you? |
|
@hanna-kruppe that sounds good! Though I will admit that it is probably better if you or someone else takes over as I am not super familiar with LLVM and codegen in general. I have updated the PR description. |
|
Also, I think we are at the point where the review comments are not something I can actively fix without a lot of help, feel free to commit directly to this PR! |
|
I’ll take the musings about further improvements to the issue, then. Thanks for your work on this! @bors r+ rollup |
…hanna-kruppe Implement `Debug` helpers via `Cell` Related to rust-lang#149745, but does not fix it (yet). Following @jmillikin's [suggestion](rust-lang#159302 (comment)), the builder logic now lives in the pre-existing non-generic methods taking `&dyn fmt::Debug` (where it used to exist), and each `*_with` method wraps its closure in a private `DebugOnce` struct that implements `Debug` by calling the closure, so the body is compiled once. Just for context: A `dyn FnOnce` [can't be called behind a reference](rust-lang#149745 (comment)), hence the `Cell<Option<..>>` stuff in `DebugOnce`. ###### repro.rs ```rust #![feature(debug_closure_helpers)] #![crate_type = "lib"] use core::fmt; pub struct Point { pub x: u32, pub y: u32, } impl fmt::Debug for Point { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Point") .field_with("x", |f| self.x.fmt(f)) .field_with("y", |f| self.y.fmt(f)) .finish() } } ``` ```bash rustc +nightly --edition=2024 --emit=llvm-ir -Copt-level=0 -o before.ll repro.rs rustc +stage1 --edition=2024 --emit=llvm-ir -Copt-level=0 -o after.ll repro.rs ``` On the repro above, I saw the LLVM IR drop from 739 to 268 lines (an earlier version of this PR using `&mut dyn FnMut` measured 372). Since the stable `&dyn fmt::Debug` methods no longer go through any closure indirection, this should also avoid the potential runtime regression in the `derive(Debug)` microbenchmark. This was the only remaining [blocker](rust-lang#117729 (comment)) for stabilizing `debug_closure_helpers`, so it should unblock rust-lang#146099.
Rollup of 10 pull requests Successful merges: - #156977 (interpret: properly check for inhabitedness of nested references) - #159365 (fix: point at method call chain when a return-position `impl Trait` assoc type diverges) - #159402 (Clarify safety requirements for SIMD shl/shr and masked load/store) - #159410 (rustdoc: remove old `--emit` types) - #159302 (Implement `Debug` helpers via `Cell`) - #159386 (add a fallback for `fmuladdf*`) - #159391 (Update tests for LLVM 23) - #159400 (Update books) - #159401 (Gate `tests/debuginfo/function-call.rs` on min GDB 15.1) - #159404 ([aarch64][win] Pass oversized c-variadic args indirectly on Arm64EC)
…hanna-kruppe Implement `Debug` helpers via `Cell` Related to rust-lang#149745, but does not fix it (yet). Following @jmillikin's [suggestion](rust-lang#159302 (comment)), the builder logic now lives in the pre-existing non-generic methods taking `&dyn fmt::Debug` (where it used to exist), and each `*_with` method wraps its closure in a private `DebugOnce` struct that implements `Debug` by calling the closure, so the body is compiled once. Just for context: A `dyn FnOnce` [can't be called behind a reference](rust-lang#149745 (comment)), hence the `Cell<Option<..>>` stuff in `DebugOnce`. ###### repro.rs ```rust #![feature(debug_closure_helpers)] #![crate_type = "lib"] use core::fmt; pub struct Point { pub x: u32, pub y: u32, } impl fmt::Debug for Point { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Point") .field_with("x", |f| self.x.fmt(f)) .field_with("y", |f| self.y.fmt(f)) .finish() } } ``` ```bash rustc +nightly --edition=2024 --emit=llvm-ir -Copt-level=0 -o before.ll repro.rs rustc +stage1 --edition=2024 --emit=llvm-ir -Copt-level=0 -o after.ll repro.rs ``` On the repro above, I saw the LLVM IR drop from 739 to 268 lines (an earlier version of this PR using `&mut dyn FnMut` measured 372). Since the stable `&dyn fmt::Debug` methods no longer go through any closure indirection, this should also avoid the potential runtime regression in the `derive(Debug)` microbenchmark. This was the only remaining [blocker](rust-lang#117729 (comment)) for stabilizing `debug_closure_helpers`, so it should unblock rust-lang#146099.
View all comments
Related to #149745, but does not fix it (yet).
Following @jmillikin's suggestion, the builder logic now lives in the pre-existing non-generic methods taking
&dyn fmt::Debug(where it used to exist), and each*_withmethod wraps its closure in a privateDebugOncestruct that implementsDebugby calling the closure, so the body is compiled once.Just for context: A
dyn FnOncecan't be called behind a reference, hence theCell<Option<..>>stuff inDebugOnce.repro.rs
On the repro above, I saw the LLVM IR drop from 739 to 268 lines (an earlier version of this PR using
&mut dyn FnMutmeasured 372). Since the stable&dyn fmt::Debugmethods no longer go through any closure indirection, this should also avoid the potential runtime regression in thederive(Debug)microbenchmark.This was the only remaining blocker for stabilizing
debug_closure_helpers, so it should unblock #146099.